/**
 * 聊天控制器
 * 处理聊天相关的HTTP请求
 */
const llmService = require('../services/llm');
const mcpClient = require('../utils/mcp-client');
const sseController = require('./sse');
const { generateId } = require('../utils/id-generator');
const { log } = require('../middleware/logger');

class ChatController {
  /**
   * 处理聊天消息
   * @param {Object} ctx - Koa上下文
   */
  async sendMessage(ctx) {
    try {
      const { message, conversationId, connectionId } = ctx.request.body;

      // 验证必需参数
      if (!message || !conversationId || !connectionId) {
        ctx.status = 400;
        ctx.body = {
          success: false,
          error: {
            message: '缺少必需参数：message, conversationId, connectionId',
            code: 'MISSING_PARAMETERS'
          }
        };
        return;
      }

      // 验证SSE连接是否存在
      const connection = sseController.getConnection(connectionId);
      if (!connection) {
        ctx.status = 400;
        ctx.body = {
          success: false,
          error: {
            message: 'SSE连接不存在或已断开',
            code: 'CONNECTION_NOT_FOUND'
          }
        };
        return;
      }

      log.info('收到聊天消息', {
        conversationId,
        connectionId,
        messageLength: message.length
      });

      // 发送处理状态
      sseController.sendStatus(connectionId, 'processing', '正在处理您的消息...');

      // 获取可用工具
      const availableTools = mcpClient.getAvailableTools();

      // 处理消息（流式）
      await this.processMessageStream(message, conversationId, connectionId, availableTools);

      // 返回成功响应
      ctx.body = {
        success: true,
        data: {
          message: '消息处理中',
          conversationId,
          connectionId
        }
      };

    } catch (error) {
      log.error('处理聊天消息失败', error);

      // 如果有连接ID，发送错误事件
      const { connectionId } = ctx.request.body;
      if (connectionId) {
        sseController.sendError(connectionId, error.message, 'PROCESSING_ERROR');
      }

      ctx.status = 500;
      ctx.body = {
        success: false,
        error: {
          message: error.message,
          code: 'PROCESSING_ERROR'
        }
      };
    }
  }

  /**
   * 流式处理消息
   * @param {string} message - 用户消息
   * @param {string} conversationId - 对话ID
   * @param {string} connectionId - 连接ID
   * @param {Array} availableTools - 可用工具列表
   */
  async processMessageStream(message, conversationId, connectionId, availableTools) {
    try {
      // 获取流式响应
      const stream = await llmService.processMessageStream(message, conversationId, availableTools);

      let fullContent = '';
      let currentToolCalls = [];
      let assistantMessage = null;

      // 处理流式响应
      for await (const chunk of stream) {
        const delta = chunk.choices[0]?.delta;

        if (!delta) continue;

        // 处理文本内容
        if (delta.content) {
          fullContent += delta.content;
          sseController.sendTextChunk(connectionId, delta.content, false);
        }

        // 处理工具调用
        if (delta.tool_calls) {
          for (const toolCall of delta.tool_calls) {
            if (!currentToolCalls[toolCall.index]) {
              currentToolCalls[toolCall.index] = {
                id: toolCall.id,
                type: toolCall.type,
                function: { name: '', arguments: '' }
              };
            }

            if (toolCall.function?.name) {
              currentToolCalls[toolCall.index].function.name += toolCall.function.name;
            }

            if (toolCall.function?.arguments) {
              currentToolCalls[toolCall.index].function.arguments += toolCall.function.arguments;
            }
          }
        }

        // 检查是否完成
        if (chunk.choices[0]?.finish_reason) {
          const finishReason = chunk.choices[0].finish_reason;

          if (finishReason === 'tool_calls' && currentToolCalls.length > 0) {
            // 需要调用工具
            assistantMessage = {
              role: 'assistant',
              content: fullContent || null,
              tool_calls: currentToolCalls.filter(tc => tc && tc.function.name)
            };

            await this.handleToolCalls(assistantMessage, conversationId, connectionId);
          } else {
            // 普通文本响应完成
            sseController.sendTextChunk(connectionId, '', true);
            // 新增：在流式完成后补发一条标准消息事件，兼容前端对 sse:message 的处理
            sseController.sendMessage(connectionId, {
              type: 'assistant',
              content: fullContent || ''
            });
            sseController.sendStatus(connectionId, 'completed', '消息处理完成');
          }
          break;
        }
      }

    } catch (error) {
      log.error('流式处理消息失败', error);
      sseController.sendError(connectionId, error.message, 'STREAM_ERROR');
    }
  }

  /**
   * 处理工具调用（支持循环处理）
   * @param {Object} assistantMessage - 助手消息
   * @param {string} conversationId - 对话ID
   * @param {string} connectionId - 连接ID
   */
  async handleToolCalls(assistantMessage, conversationId, connectionId) {
    try {
      let currentMessage = assistantMessage;
      let iterationCount = 0;
      const maxIterations = 10; // 防止无限循环

      while (currentMessage.tool_calls && currentMessage.tool_calls.length > 0 && iterationCount < maxIterations) {
        iterationCount++;
        log.info('开始工具调用循环', { iterationCount, toolCallsCount: currentMessage.tool_calls.length });

        // 处理当前的工具调用
        const toolResults = [];
        for (const toolCall of currentMessage.tool_calls) {
          // 发送工具调用开始事件
          sseController.sendToolCallStart(connectionId, toolCall);

          try {
            // 解析工具参数
            const parameters = JSON.parse(toolCall.function.arguments);
            log.info('工具调用参数', { toolCall, parameters });

            // 调用MCP工具
            const result = await mcpClient.callTool(toolCall.function.name, parameters);

            // 发送工具调用结果
            sseController.sendToolCallResult(connectionId, toolCall, result);

            toolResults.push({
              toolCall,
              result
            });

          } catch (toolError) {
            log.error('工具调用失败', { toolCall, error: toolError.message });
            const errorResult = {
              success: false,
              error: {
                message: toolError.message,
                code: 'TOOL_ERROR'
              }
            };
            sseController.sendError(connectionId, `工具调用失败: ${toolError.message}`, 'TOOL_ERROR');
            
            toolResults.push({
              toolCall,
              result: errorResult
            });
          }
        }

        // 将工具调用结果发送给LLM，获取下一步响应
        const nextResponse = await llmService.processToolResults(
          conversationId,
          currentMessage,
          toolResults
        );

        if (nextResponse.type === 'tool_calls') {
          // LLM返回了新的工具调用，继续循环
          currentMessage = nextResponse.message;
          log.info('LLM返回新的工具调用，继续处理', { 
            newToolCallsCount: currentMessage.tool_calls.length 
          });
        } else {
          // LLM返回了最终文本响应，结束循环
          log.info('LLM返回最终响应，结束工具调用循环', { 
            responseType: nextResponse.type,
            contentLength: nextResponse.content?.length || 0
          });

          // 发送最终响应
          sseController.sendMessage(connectionId, {
            type: 'assistant',
            content: nextResponse.content
          });
          
          break;
        }
      }

      if (iterationCount >= maxIterations) {
        log.warn('工具调用循环达到最大迭代次数', { maxIterations });
        sseController.sendError(connectionId, '工具调用循环次数过多，已终止处理', 'MAX_ITERATIONS_EXCEEDED');
      }

      sseController.sendStatus(connectionId, 'completed', '消息处理完成');

    } catch (error) {
      log.error('处理工具调用失败', error);
      sseController.sendError(connectionId, error.message, 'TOOL_PROCESSING_ERROR');
    }
  }

  /**
   * 创建新对话
   * @param {Object} ctx - Koa上下文
   */
  async createConversation(ctx) {
    try {
      const conversationId = generateId();

      log.info('创建新对话', { conversationId });

      ctx.body = {
        success: true,
        data: {
          conversationId,
          createdAt: new Date().toISOString(),
          title: '新对话'
        }
      };

    } catch (error) {
      log.error('创建对话失败', error);

      ctx.status = 500;
      ctx.body = {
        success: false,
        error: {
          message: error.message,
          code: 'CONVERSATION_CREATION_ERROR'
        }
      };
    }
  }

  /**
   * 获取对话信息
   * @param {Object} ctx - Koa上下文
   */
  async getConversation(ctx) {
    try {
      const { conversationId } = ctx.params;

      if (!conversationId) {
        ctx.status = 400;
        ctx.body = {
          success: false,
          error: {
            message: '缺少对话ID',
            code: 'MISSING_CONVERSATION_ID'
          }
        };
        return;
      }

      // 获取对话上下文
      const context = llmService.getConversationContext(conversationId);

      ctx.body = {
        success: true,
        data: {
          conversationId: context.id,
          messageCount: context.messages.length,
          createdAt: context.createdAt,
          lastActivity: context.lastActivity
        }
      };

    } catch (error) {
      log.error('获取对话信息失败', error);

      ctx.status = 500;
      ctx.body = {
        success: false,
        error: {
          message: error.message,
          code: 'GET_CONVERSATION_ERROR'
        }
      };
    }
  }

  /**
   * 清理对话
   * @param {Object} ctx - Koa上下文
   */
  async clearConversation(ctx) {
    try {
      const { conversationId } = ctx.params;

      if (!conversationId) {
        ctx.status = 400;
        ctx.body = {
          success: false,
          error: {
            message: '缺少对话ID',
            code: 'MISSING_CONVERSATION_ID'
          }
        };
        return;
      }

      // 清理对话上下文
      llmService.clearConversationContext(conversationId);

      log.info('清理对话', { conversationId });

      ctx.body = {
        success: true,
        data: {
          message: '对话已清理',
          conversationId
        }
      };

    } catch (error) {
      log.error('清理对话失败', error);

      ctx.status = 500;
      ctx.body = {
        success: false,
        error: {
          message: error.message,
          code: 'CLEAR_CONVERSATION_ERROR'
        }
      };
    }
  }

  /**
   * 获取可用工具列表
   * @param {Object} ctx - Koa上下文
   */
  async getAvailableTools(ctx) {
    try {
      const tools = mcpClient.getAvailableTools();

      ctx.body = {
        success: true,
        data: {
          tools,
          count: tools.length
        }
      };

    } catch (error) {
      log.error('获取工具列表失败', error);

      ctx.status = 500;
      ctx.body = {
        success: false,
        error: {
          message: error.message,
          code: 'GET_TOOLS_ERROR'
        }
      };
    }
  }
}

// 创建单例实例
const chatController = new ChatController();

module.exports = chatController;